﻿// Inner Fire 游戏引擎库
// 渲染对象
//
// Copyright (c) 2023 by 尔西大帝. All rights reserved.
//
// 渲染对象。根据《DirectX12游戏开发实战》中的工具类修改。
// 原作者：Frank Luna
//
// Author: 尔西大帝
// Email: 2670613871@qq.com
// Created: 2024-11-27

#include "render_target.h"
#include <dx/core/dx_exception.h>

namespace ifire::dx {

RenderTarget::RenderTarget(
    ID3D12Device* device, UINT width, UINT height, DXGI_FORMAT format)
    : RenderTexture(device, width, height, format) {
  BuildResource();
}

ID3D12Resource* RenderTarget::Resource() { return mOffscreenTex.Get(); }


void RenderTarget::BuildDescriptors(CD3DX12_CPU_DESCRIPTOR_HANDLE hCpuSrv,
    CD3DX12_GPU_DESCRIPTOR_HANDLE hGpuSrv,
    CD3DX12_CPU_DESCRIPTOR_HANDLE hCpuRtv) {
  // Save references to the descriptors.
  mhCpuSrv = hCpuSrv;
  mhGpuSrv = hGpuSrv;
  mhCpuRtv = hCpuRtv;

  BuildDescriptors();
}

void RenderTarget::BuildDescriptors() {
  D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
  srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
  srvDesc.Format = format_;
  srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
  srvDesc.Texture2D.MostDetailedMip = 0;
  srvDesc.Texture2D.MipLevels = 1;

  device_->CreateShaderResourceView(mOffscreenTex.Get(), &srvDesc, mhCpuSrv);

  device_->CreateRenderTargetView(mOffscreenTex.Get(), nullptr, mhCpuRtv);
}

void RenderTarget::BuildResource() {
  // Note, compressed formats cannot be used for UAV.  We get error like:
  // ERROR: ID3D11Device::CreateTexture2D: The format (0x4d, BC3_UNORM)
  // cannot be bound as an UnorderedAccessView, or cast to a format that
  // could be bound as an UnorderedAccessView.  Therefore this format
  // does not support D3D11_BIND_UNORDERED_ACCESS.

  D3D12_RESOURCE_DESC texDesc;
  ZeroMemory(&texDesc, sizeof(D3D12_RESOURCE_DESC));
  texDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
  texDesc.Alignment = 0;
  texDesc.Width = width_;
  texDesc.Height = height_;
  texDesc.DepthOrArraySize = 1;
  texDesc.MipLevels = 1;
  texDesc.Format = format_;
  texDesc.SampleDesc.Count = 1;
  texDesc.SampleDesc.Quality = 0;
  texDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
  texDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;

  clearValue.Format = BACK_BUFFER_FORMAT; // 根据你的渲染目标格式设置
  clearValue.Color[0] = 0.7f;             // R
  clearValue.Color[1] = 0.7f;             // G
  clearValue.Color[2] = 1.0f;             // B
  clearValue.Color[3] = 1.0f;             // A
  auto default_props = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT);
  HASSERT(device_->CreateCommittedResource(&default_props,
      D3D12_HEAP_FLAG_NONE, &texDesc, D3D12_RESOURCE_STATE_GENERIC_READ,
      &clearValue, IID_PPV_ARGS(&mOffscreenTex)));
}

} // namespace ifire